package com.cinco.blog.service.impl;

import com.cinco.blog.NotFoundException;
import com.cinco.blog.dao.BlogDao;
import com.cinco.blog.po.Blog;
import com.cinco.blog.service.BlogService;
import com.cinco.blog.utiil.MarkdownUtils;
import com.cinco.blog.utiil.MyBeanUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.thymeleaf.util.StringUtils;

import javax.persistence.criteria.*;
import java.util.*;

@Service
public class BlogServiceImpl implements BlogService {

    @Autowired
    private BlogDao blogDao;

    @Override
    public Blog getBlog(Long id) {
        return blogDao.getById(id);
    }

    public List<Blog> findAllwx(){
        return blogDao.findAllwx();
    }

    @Transactional
    @Override
    public Blog getBlogWx(Long id) {
        blogDao.updateViews(id);
        return blogDao.getByIdWx(id);
    }

    @Transactional
    @Override
    public Blog getAndConvert(Long id) {
        Blog blog = blogDao.getById(id);
        if (blog == null){
            throw new NotFoundException("该博客不存在");
        }
        Blog b = new Blog();
        BeanUtils.copyProperties(blog,b);
        String context = b.getContent();
        b.setContent(MarkdownUtils.markdownToHtmlExtensions(context));
        blogDao.updateViews(id);
        return b;
    }

    @Override
    public Page<Blog> listBlog(Pageable pageable, Blog blog) {

//        Example<Blog> example = Example.of(blog);
        ExampleMatcher matcher = ExampleMatcher.matching()
                .withIgnorePaths("shareStatement","commentabled","published","appreciation","id");      //查询时首先要忽略这些空值

        //标题没有值就把它忽略掉
        if (StringUtils.isEmptyOrWhitespace(blog.getTitle())){
            matcher = matcher.withIgnorePaths("title");
        }else{
            //标题不为空就设置标题模糊查询  contains: 查找包含此字符串的结果
            matcher = matcher.withMatcher("title",ExampleMatcher.GenericPropertyMatchers.contains());
        }
        //类型没有选上就把它忽略掉
        if (blog.getType() == null){
            matcher = matcher.withIgnorePaths("type");
        }
        //推荐没有选上就把它忽略掉
        if (!blog.isRecommend()){ matcher = matcher.withIgnorePaths("recommend"); }

        Example<Blog> example = Example.of(blog,matcher);
        Page<Blog> all = blogDao.findAll(example, pageable);

        return all;
    }

    @Override
    public Page<Blog> listBlog(Long tagId, Pageable pageable) {
        return blogDao.findAll(new Specification<Blog>() {
            @Override
            public Predicate toPredicate(Root<Blog> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {
                Join join = root.join("tags");
                return cb.equal(join.get("id"), tagId);
            }
        }, pageable);
    }

    @Override
    public Page<Blog> listBlog(Pageable pageable) {
        return blogDao.findAll(pageable);
    }

    @Override
    public Page<Blog> listBlog(String query, Pageable pageable) {
        return blogDao.findByQuery("%"+query+"%",pageable);
    }
    @Override
    public List<Blog> listRecommendBlogTop(Integer size) {

        Sort sort = Sort.by(Sort.Direction.DESC, "updateTime");
        Pageable pageable = PageRequest.of(0,size,sort);
        return blogDao.findTop(pageable);
    }

    @Override
    public Map<String, List<Blog>> archivesBlog() {
        List<String> years = blogDao.findGroupYear();
        Map<String, List<Blog>> map = new HashMap<>();
        for (String year : years) {
            map.put(year,blogDao.findByYear(year));
        }
        return map;
    }

    @Override
    public Long countBlog() {
        //返回blog表里的数据数量
        return blogDao.count();
    }

    @Override
    @Transactional
    public Blog saveBlog(Blog blog) {
        if(blog.getId() == null){       //新增操作时blog没有id
            blog.setCreateTime(new Date());
            blog.setUpdateTime(new Date());
            blog.setViews(0);
        }else{
            blog.setUpdateTime(new Date());
        }

        return blogDao.save(blog);
    }

    @Override
    @Transactional
    public Blog updateBlog(Long id, Blog blog) {

        Blog b = blogDao.getById(id);
        if (b == null){
            throw new NotFoundException("该博客不存在");
        }

        /*把前端传过来的blog对象中的非空字段赋值给b，并且给更新时间赋值，然后对b进行更新操作
        * 避免了把控制也更新到数据库
        * */
        BeanUtils.copyProperties(blog,b, MyBeanUtils.getNullPropertyNames(blog));
        b.setUpdateTime(new Date());
        return blogDao.save(b);
    }

    @Override
    @Transactional
    public void deleteBlog(Long id) {
        blogDao.deleteById(id);
    }

    @Override
    @Transactional
    public void updateViews(Long id){
        blogDao.updateViews(id);
    }
}
